#include "include/TcpConnection.hpp"
#include "include/EventLoop.hpp"
#include <header.h>
#include <sstream>
#include <ostream>
using namespace std;

TcpConnection::TcpConnection(int fd,EventLoop * loop)
    :_sock(fd)
    ,_sockIO(fd)
    ,_local(getLocalAddr())
    ,_peer(getPeerAddr())
    ,_loop(loop)
{}

bool TcpConnection::isClosed(){
    char buff[1024]={0};
    if(_sockIO.recvPeek(buff,sizeof(buff))<=0)return true;
    return false;
}

string TcpConnection::recieve(){
    char buff[65536] = {0};
    int ret = _sockIO.readline(buff,sizeof(buff));
    //防止buff中有'\0'
    return string(buff,ret);
}

Packet TcpConnection::recvPacket(){
    return _sockIO.recvPacket();
}

void TcpConnection::send(const string & msg){
    if(msg.size()>0)
    _sockIO.sendn(msg.c_str(),msg.size());
}

void TcpConnection::shutdown(){
    _sock.shutdownPtr();
}

string TcpConnection::toString()const{
    stringstream sstr;
    sstr.str("");
    sstr.clear();
    sstr<<"tcp"<<_local.ip()<<":"<<_local.port()<<" -> " << _peer.ip() << ":" << _peer.port(); 
    return sstr.str();
}

InetAddress  TcpConnection::getLocalAddr(){
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);
    int ret  = getsockname(_sock.fd(),(struct sockaddr*)&addr,&len);
    if(ret <0){
        perror("getsockname");
    }
    return InetAddress(ntohs(addr.sin_port),inet_ntoa(addr.sin_addr));
}
InetAddress  TcpConnection::getPeerAddr(){
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);
    int ret  = getpeername(_sock.fd(),(struct sockaddr*)&addr,&len);
    if(ret <0){
        perror("getPeername");
    }
    return InetAddress(ntohs(addr.sin_port),inet_ntoa(addr.sin_addr));
}

void TcpConnection::handleNewConnectCallBack(){
    if(_onConnection){
        _onConnection(shared_from_this());
    }
}
void TcpConnection::handleMessageCallBack(){
    if(_onMessage){
        _onMessage(shared_from_this());
    }
}
void TcpConnection::handleCloseCallBack(){
    if(_onclose){
        _onclose(shared_from_this());
    }
}

void TcpConnection::sendInLoop(const string & msg){
    _loop->runInLoop(std::bind(&TcpConnection::send,this,msg));
}


